package com.jiangyg.mall.product.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.jiangyg.mall.core.exception.BusinessException;
import com.jiangyg.mall.db.mybatis.BaseServiceImpl;
import com.jiangyg.mall.core.support.restful.Pagination;
import com.jiangyg.mall.core.utils.Assert;
import com.jiangyg.mall.core.utils.bean.BeanUtils;
import com.jiangyg.mall.core.utils.tree.Tree;
import com.jiangyg.mall.core.utils.tree.TreeUtils;
import com.jiangyg.mall.product.constant.ColumnConstant;
import com.jiangyg.mall.product.constant.ProductConstant;
import com.jiangyg.mall.product.dto.CategoryDTO;
import com.jiangyg.mall.product.entity.Category;
import com.jiangyg.mall.product.entity.CategoryBrand;
import com.jiangyg.mall.product.enums.Visible;
import com.jiangyg.mall.product.vo.CategoryVO;
import com.jiangyg.mall.product.dao.CategoryBrandDao;
import com.jiangyg.mall.product.dao.CategoryDao;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Service
public class CategoryServiceImpl extends BaseServiceImpl<CategoryDao, Category> implements CategoryService {

    /**
     * 分类品牌关联
     */
    private final CategoryBrandDao categoryBrandDao;

    @Autowired
    public CategoryServiceImpl(CategoryDao categoryDao,
                               CategoryBrandDao categoryBrandDao) {
        super(categoryDao);
        this.categoryBrandDao = categoryBrandDao;
    }

    @Override
    public List<Tree> tree() throws Exception {
        // 查询显示状态的目录
        final QueryWrapper<Category> wrapper = new QueryWrapper<>();
        wrapper.eq(ColumnConstant.VISIBLE, Visible.Y.code);
        List<Category> categories = this.baseMapper.selectList(wrapper);
        // 树形结构转换
        List<CategoryVO> dtos = BeanUtils.transformList(categories, CategoryVO.class);
        final List<Tree> trees = dtos.stream().map(CategoryVO::toTree).collect(Collectors.toList());
        return TreeUtils.instance(trees).getTree();
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<Tree> mtree() throws Exception {
        List<Category> categories = this.baseMapper.selectList(null);
        List<CategoryVO> dtos = BeanUtils.transformList(categories, CategoryVO.class);
        final List<Tree> trees = dtos.stream().map(CategoryVO::toMTree).collect(Collectors.toList());
        return TreeUtils.instance(trees).getTree();
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public Pagination<CategoryDTO> selectPagination(Pagination<CategoryDTO> pagination) throws Exception {
        return this.executeSelectPagination(pagination, CategoryDTO.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveOrUpdate(CategoryDTO dto) throws Exception {
        // 父级分类ID默认处理
        if (dto.getPid() == null) {
            dto.setPid(ProductConstant.ROOT_ID);
        }
        Category category;
        final Long id = dto.getId();
        // 修改分类信息
        if (id != null && (category = this.baseMapper.selectById(id)) != null) {
            // 如果名称修改，则需要修改品牌分类关联表的分类名称
            if (!StringUtils.equals(dto.getName(), category.getName())) {
                final CategoryBrand categoryBrand = new CategoryBrand();
                categoryBrand.setCategoryName(dto.getName());
                final UpdateWrapper<CategoryBrand> wrapper = new UpdateWrapper<>();
                wrapper.eq(ColumnConstant.CATEGORY_ID, dto.getId());
                this.categoryBrandDao.update(categoryBrand, wrapper);
            }
            BeanUtils.copyProperties(category, dto);
            return this.baseMapper.updateById(category) > 0;
        }
        // 新增分类
        category = new Category();
        BeanUtils.copyProperties(category, dto);
        return this.baseMapper.insert(category) > 0;
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public CategoryVO selectById(Long categoryId) throws Exception {
        final CategoryVO dto = this.executeSelectById(categoryId, CategoryVO.class);
        // 父级菜单名称
        if (dto != null) {
            if (dto.getPid().equals(ProductConstant.ROOT_ID.toString())) {
                dto.setPname("跟节点");
            } else {
                final Category p = this.baseMapper.selectById(dto.getPid());
                dto.setPname(p.getName());
            }
        }
        return dto;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delete(List<Long> categoryIds) {
        Assert.notEmpty(categoryIds);
        // 判断分类是否有子集
        {
            final QueryWrapper<Category> wrapper = new QueryWrapper<>();
            wrapper.in(ColumnConstant.PID, categoryIds);
            final Integer count = this.baseMapper.selectCount(wrapper);
            if (count > 0) {
                throw BusinessException.instance("mall.product.category.delete.haveChildren");
            }
        }
        // 判断分类下是否存在品牌
        {
            final QueryWrapper<CategoryBrand> wrapper = new QueryWrapper<>();
            wrapper.in(ColumnConstant.CATEGORY_ID, categoryIds);
            final Integer count = categoryBrandDao.selectCount(wrapper);
            if (count > 0) {
                throw BusinessException.instance("mall.product.category.delete.haveBrand");
            }
        }
        // 执行删除
        return this.baseMapper.deleteBatchIds(categoryIds) > 0;
    }

}
